#ifndef _TABLE_SCHEMA_H__
#define _TABLE_SCHEMA_H__
#include <vector>
#include <map>
using namespace std;
#include <proc/connection.h>
using namespace Oracle;

enum ColumnType
{
	DBCOL_TYPE_UNKNOW = 0,
	DBCOL_TYPE_CHAR,
	DBCOL_TYPE_VARCHAR,
	DBCOL_TYPE_VARCHAR2,
	DBCOL_TYPE_SHORT,
	DBCOL_TYPE_INTEGER,
	DBCOL_TYPE_NUMBER,
	DBCOL_TYPE_FLOAT,
	DBCOL_TYPE_DECIMAL,
	DBCOL_TYPE_MONEY,
	DBCOL_TYPE_DATE,
	DBCOL_TYPE_TIMESTAMP,
	DBCOL_TYPE_INTERVAL,
	DBCOL_TYPE_BLOB
};

enum IndexType
{
	UniqueIndex = 0,
	DuplexIndex
};

enum IndexColumnType
{
	Ascend = 0,
	Desend
};

struct Column
{
	string name;
	ColumnType type;
	int length;
	int id;
	int precision;
	int scale;
	bool nullable;
};

struct IndexColumn
{
	string name;
	IndexColumnType type;
};

struct Index
{
	string name;
	IndexType type;
	vector<IndexColumn> indexColumns;
};

class Table
{
friend class TableSchema;
public:
	const string &getName() const
	{
		return name;
	}
	const string &getTbsName() const
	{
		return tbs_name;
	}
	bool view() const
	{
		return isView;
	}
	const vector<Column> &getColumns() const
	{
		return cols;
	}
	const vector<Index> &getIndexs() const
	{
		return indexs;
	}
	bool colNullable(const string &columnName) const
	{
		vector<Column>::const_iterator iter;
		for (iter=cols.begin(); iter!=cols.end(); iter++){
			if (iter->name == columnName){
				return iter->nullable;
			}
		}
		return false;
	}
	ColumnType getColumnType(const string &name) const
	{
		vector<Column>::const_iterator iter;
		for (iter=cols.begin(); iter!=cols.end(); iter++){
			if (iter->name == name){
				return iter->type;
			}
		}
		return DBCOL_TYPE_UNKNOW;
	}
	const Index *getUniqueIndex() const
	{
		int i;
		vector<Index>::const_iterator iter;
		for (iter=indexs.begin(),i=0; iter!=indexs.end(); iter++,i++){
			if (iter->type == UniqueIndex){
				return &(indexs[i]);
			}
		}
		return 0;
	}


private:	
	string name;
	string tbs_name;
	bool isView;
	int num_rows;
	vector<Column> cols;
	vector<Index> indexs;
};

class TableSchema
{
public:
	TableSchema(Connection &connection, const char *tablename);
	
	bool open();
	
	const string &getTableName() const
	{
		return tablename;
	}
	
	const Table &getTable() const 
	{
		return table;
	}
	
	const string & mapColumnType(ColumnType columnType) const
	{
		map<ColumnType, string>::const_iterator iter;
		iter = typeMap2.find(columnType);
		if (iter == typeMap2.end()){
			return unknown;
		}
		return iter->second;
	}
	
private:
	bool getTableSpace();
	bool getViewTableSpace();
	bool getColumns();
	bool getIndexs();
	
	void initTypeMap();
	void initTypeMap2();
	
private:
	Table table;
	string tablename;
	Connection &connection;
	map<string, ColumnType> typeMap;
	map<ColumnType, string> typeMap2;
	string unknown;
};

#endif
